{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b660009d",
   "metadata": {},
   "source": [
    "**MACHINE LEARNING**\n",
    "\n",
    "**HRV for detecting arousal**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "783cb4b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Libraries\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.model_selection import LeaveOneGroupOut, KFold, GridSearchCV\n",
    "from xgboost import XGBRegressor\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score, root_mean_squared_error\n",
    "import numpy as np\n",
    "from sklearn.model_selection import GridSearchCV, KFold\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from sklearn.ensemble import RandomForestRegressor\n",
    "from sklearn.feature_selection import mutual_info_regression\n",
    "from sklearn.svm import SVR\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.pipeline import make_pipeline\n",
    "from scipy.stats import pearsonr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "31ad199b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2052"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Loading the dataset\n",
    "file = r\"C:\\Users\\Salin\\OneDrive\\Documentos\\ESSEX\\DSPROJECT\\PPG_HR_Analysis_Longer_Intervals_\\PPG\\merged_features_norm_grey_new_arousal.csv\"\n",
    "df = pd.read_csv(file)\n",
    "\n",
    "# Displaying info\n",
    "df.head()\n",
    "len(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "7acd5ce1",
   "metadata": {},
   "outputs": [],
   "source": [
    "X = df.drop(columns=['Participant', 'Stimulus', 'Arousal'])\n",
    "y = df['Arousal']\n",
    "groups = df['Participant']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "ffa71ade",
   "metadata": {},
   "outputs": [],
   "source": [
    "def concordance_correlation_coefficient(y_true, y_pred):\n",
    "    mean_true = np.mean(y_true)\n",
    "    mean_pred = np.mean(y_pred)\n",
    "    var_true = np.var(y_true)\n",
    "    var_pred = np.var(y_pred)\n",
    "    covariance = np.mean((y_true - mean_true) * (y_pred - mean_pred))\n",
    "\n",
    "    ccc = (2 * covariance) / (var_true + var_pred + (mean_true - mean_pred)**2 + 1e-8)\n",
    "    return ccc\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "9a0406a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "def evaluate_regression(true_values, predicted_values, results_df):\n",
    "    mse = mean_squared_error(true_values, predicted_values)\n",
    "    rmse = np.sqrt(mse)\n",
    "    mae = mean_absolute_error(true_values, predicted_values)\n",
    "    r2 = r2_score(true_values, predicted_values)\n",
    "    corr, p = pearsonr(true_values, predicted_values)\n",
    "    ccc = concordance_correlation_coefficient(np.array(true_values), np.array(predicted_values))\n",
    "    rmse_std = results_df['RMSE'].std()\n",
    "    mae_std = results_df['MAE'].std() \n",
    "    r2_std = results_df['R2'].std() \n",
    "\n",
    "    # Output\n",
    "    print(f\"RMSE: {rmse:.3f} ± {rmse_std:.3f}\")\n",
    "    print(f\"MAE: {mae:.3f}\" + (f\" ± {mae_std:.3f}\"))\n",
    "    print(f\"R² Score: {r2:.3f}\" + (f\" ± {r2_std:.3f}\"))\n",
    "    print(f\"Correlation: {corr:.4f}\")\n",
    "    print(f\"P-value: {p:.4e}\")\n",
    "    print(f\"Concordance Correlation Coefficient (CCC): {ccc:.4f}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c93310b7",
   "metadata": {},
   "source": [
    "**XGBOOST REGRESSOR**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "9f122a22",
   "metadata": {},
   "outputs": [],
   "source": [
    "logo = LeaveOneGroupOut()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "3e584a1e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "LOPO without hyperparameter tuning:\n",
      "RMSE: 0.168 ± 0.034\n",
      "MAE: 0.132 ± 0.031\n",
      "R² Score: 0.227 ± 0.199\n",
      "Correlation: 0.5124\n",
      "P-value: 9.1424e-138\n",
      "Concordance Correlation Coefficient (CCC): 0.4814\n"
     ]
    }
   ],
   "source": [
    "true_values = []\n",
    "predicted_values = []\n",
    "results = []\n",
    "\n",
    "for train_idx, test_idx in logo.split(X, y, groups):\n",
    "    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]\n",
    "    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]\n",
    "    test_participant = groups.iloc[test_idx].unique()[0]\n",
    "\n",
    "    model = XGBRegressor(n_estimators=100, random_state=42)\n",
    "    model.fit(X_train, y_train)\n",
    "    y_pred = model.predict(X_test)\n",
    "\n",
    "    true_values.extend(y_test)\n",
    "    predicted_values.extend(y_pred)\n",
    "\n",
    "    mse = mean_squared_error(y_test, y_pred)\n",
    "    rmse = np.sqrt(mse)\n",
    "    mae = mean_absolute_error(y_test, y_pred)\n",
    "    r2 = r2_score(y_test, y_pred)\n",
    "\n",
    "    results.append({\n",
    "        'Participant': test_participant,\n",
    "        'RMSE': rmse,\n",
    "        'MAE': mae,\n",
    "        'R2': r2\n",
    "    })\n",
    "\n",
    "\n",
    "results_df = pd.DataFrame(results)\n",
    "\n",
    "print(\"LOPO without hyperparameter tuning:\")\n",
    "evaluate_regression(true_values, predicted_values, results_df)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "54033336",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "F1_CrossingPoints   -0.351969\n",
       "pVLF                -0.151748\n",
       "aVLF                -0.109718\n",
       "pLF                  0.100511\n",
       "F3_MaxArea          -0.086162\n",
       "nLF                  0.071986\n",
       "F9_KurtX            -0.060054\n",
       "aTotal              -0.053120\n",
       "nHF                 -0.046888\n",
       "NN50                -0.045010\n",
       "dtype: float64"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "global_corr = X.corrwith(y)\n",
    "global_corr = global_corr.sort_values(key=abs, ascending=False)\n",
    "global_corr.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "6d7fd6d3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Series([], dtype: int64)"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Checking number of missing values per column\n",
    "missing_counts = X.isna().sum()\n",
    "\n",
    "# Displaying only columns that have missing values\n",
    "missing_counts[missing_counts > 0].sort_values(ascending=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "d119d196",
   "metadata": {},
   "outputs": [],
   "source": [
    "X_mi = X.copy()\n",
    "\n",
    "# Filling NaNs with column means \n",
    "X_mi = X_mi.fillna(X_mi.mean())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "9cfcab84",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Axes: title={'center': 'Mutual Information Scores'}>"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA94AAAJ/CAYAAACOWgvUAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/GU6VOAAAACXBIWXMAAA9hAAAPYQGoP6dpAACk9klEQVR4nOzdeZyN9f//8eeZYWaYsQ8zCDMk6zD2UKGEUpKylmVI9M2WJUuWlBpZx1bIVkq0iIpQY6uQsmaXpRHN2LKNDGbevz/85nwcM4OR9zkTj/vtdt3qXNd1zut9ZsZ1zvO63tf77TDGGAEAAAAAACu8PN0AAAAAAADuZARvAAAAAAAsIngDAAAAAGARwRsAAAAAAIsI3gAAAAAAWETwBgAAAADAIoI3AAAAAAAWEbwBAAAAALCI4A0AAAAAgEUEbwAAbmDWrFlyOBw6ePCg1TpxcXF69tlnlSdPHjkcDkVFRVmt507t2rVTSEiIp5sBAIBHELwBALddclB1OBz68ccfU2w3xqhQoUJyOBx64oknbqnG4sWL9frrr//Llt5er7/+uhwOh44fP35Lz3/llVe0dOlS9e/fX7Nnz1aDBg1ucwvtOnLkiF5//XVt3rzZ001xcezYMXXv3l0lS5ZUlixZlC9fPlWtWlV9+/bVuXPnPN08AMBdIJOnGwAAuHP5+flpzpw5euCBB1zWr1q1Sn/++ad8fX1v+bUXL16sSZMmZbjw/W8sX75cTz31lHr37u3pptySI0eOaOjQoQoJCVF4eLjLtvfff19JSUlub9PJkydVuXJlnTlzRu3bt1fJkiV14sQJbd26Ve+9955eeuklBQQEuL1dAIC7C8EbAGDN448/rs8++0zjx49Xpkz/+8iZM2eOKlWqdMtXhu9UR48eVc6cOW/b6124cEE+Pj7y8vJ8B7fMmTN7pO706dMVExOjn376STVq1HDZdubMGfn4+LitLfHx8fL393dbPQBAxuH5T2IAwB2rZcuWOnHihL777jvnuosXL+rzzz9Xq1atUuy/cuVKORwOrVy50mX9wYMH5XA4NGvWLElX7heeNGmSJDm7tDscjnS9hiRt3bpV7dq1U9GiReXn56fg4GC1b99eJ06c+Pdv/v+rXbu2ypYtqx07dqhOnTrKmjWrChYsqBEjRjj3Se6ab4zRpEmTXN6PJO3fv19NmzZV7ty5lTVrVt1///1atGiRS53k9z137lwNHDhQBQsWVNasWXXmzBm1a9dOAQEBiomJ0RNPPKGAgAAVLFjQ+TP87bff9PDDD8vf319FihTRnDlzXF775MmT6t27t8LCwhQQEKDs2bPrscce05YtW1zqV6lSRZIUERHhfA9X/86uvcc7Pj5evXr1UqFCheTr66sSJUpo1KhRMsa47OdwONSlSxctWLBAZcuWla+vr8qUKaMlS5bc8Oe/b98+eXt76/7770+xLXv27PLz83NZ9/PPP+vxxx9Xrly55O/vr3LlymncuHEu+yxfvlwPPvig/P39lTNnTj311FPauXOnyz7Jtx3s2LFDrVq1Uq5cuVx6fnz00UeqVKmSsmTJoty5c6tFixY6dOiQy2vs3btXzzzzjIKDg+Xn56d77rlHLVq00OnTp2/4vgEAGQtXvAEA1oSEhKh69er65JNP9Nhjj0mSvv32W50+fVotWrTQ+PHjb+l1O3XqpCNHjui7777T7Nmzb7l93333nfbv36+IiAgFBwdr+/btmjp1qrZv365169a5hN9/4++//1aDBg3UpEkTNWvWTJ9//rn69u2rsLAwPfbYY3rooYc0e/ZstW7dWo8++qjatGnjfG5cXJxq1Kih8+fPq1u3bsqTJ48++OADNWrUSJ9//rmefvppl1pvvvmmfHx81Lt3byUkJDiv6CYmJjprjRgxQh9//LG6dOkif39/vfbaa3ruuefUpEkTTZ48WW3atFH16tUVGhoq6UrwX7BggZo2barQ0FDFxcVpypQpqlWrlnbs2KECBQqoVKlSeuONNzR48GC9+OKLevDBByUpxVXmZMYYNWrUSCtWrFCHDh0UHh6upUuXqk+fPjp8+LDGjh3rsv+PP/6o+fPn6//+7/+ULVs2jR8/Xs8884xiYmKUJ0+eNH/2RYoUUWJiombPnq22bdte9/f03Xff6YknnlD+/PnVvXt3BQcHa+fOnfrmm2/UvXt3SdL333+vxx57TEWLFtXrr7+uf/75RxMmTFDNmjW1cePGFCcXmjZtquLFi+vtt992nlB46623NGjQIDVr1kwvvPCCjh07pgkTJuihhx7Spk2blDNnTl28eFH169dXQkKCunbtquDgYB0+fFjffPONTp06pRw5clz3vQAAMhgDAMBtNnPmTCPJ/PLLL2bixIkmW7Zs5vz588YYY5o2bWrq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/BQWFqbFixc7t126dEl9+/ZVWFiY/P39VaBAAbVp00ZHjhy5laYBAAAAAJChpDt4z5s3Tz179tSQIUO0ceNGlS9fXvXr19fRo0dT3X/NmjVq2bKlOnTooE2bNqlx48Zq3Lixtm3bJkk6f/68Nm7cqEGDBmnjxo2aP3++du/erUaNGv27dwYAAAAAQAaQ7uA9ZswYdezYURERESpdurQmT56srFmzasaMGanuP27cODVo0EB9+vRRqVKl9Oabb6pixYqaOHGiJClHjhz67rvv1KxZM5UoUUL333+/Jk6cqA0bNigmJubfvTsAAAAAADwsXcH74sWL2rBhg+rWrfu/F/DyUt26dbV27dpUn7N27VqX/SWpfv36ae4vSadPn5bD4VDOnDnT3CchIUFnzpxxWQAAAAAAyGjSFbyPHz+uxMREBQUFuawPCgpSbGxsqs+JjY1N1/4XLlxQ37591bJlS2XPnj3NtkRGRipHjhzOpVChQul5KwAAAAAAuEWGGtX80qVLatasmYwxeu+99667b//+/XX69GnncujQITe1EgAAAACAm5cpPTsHBgbK29tbcXFxLuvj4uIUHByc6nOCg4Nvav/k0P3HH39o+fLl173aLUm+vr7y9fVNT/MBAAAAAHC7dF3x9vHxUaVKlRQdHe1cl5SUpOjoaFWvXj3V51SvXt1lf0n67rvvXPZPDt179+7V999/rzx58qSnWQAAAAAAZFjpuuItST179lTbtm1VuXJlVa1aVVFRUYqPj1dERIQkqU2bNipYsKAiIyMlSd27d1etWrU0evRoNWzYUHPnztWvv/6qqVOnSroSup999llt3LhR33zzjRITE533f+fOnVs+Pj63670CAAAAAOB26Q7ezZs317FjxzR48GDFxsYqPDxcS5YscQ6gFhMTIy+v/11Ir1GjhubMmaOBAwdqwIABKl68uBYsWKCyZctKkg4fPqyvvvpKkhQeHu5Sa8WKFapdu/YtvjUAAAAAADwv3cFbkrp06aIuXbqkum3lypUp1jVt2lRNmzZNdf+QkBAZY26lGQCA/4iQfov+1fMPDm94m1oCAADgfrcUvAEA+C8h+AMAAE/KUNOJAQAAAABwpyF4AwAAAABgEcEbAAAAAACLuMcbAAA34D5zAADuXlzxBgAAAADAIoI3AAAAAAAW0dUcAIC7AF3dAQDwHK54AwAA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WjW99NJLabbp/fffv+11kwUGBurQoUMKCQlxadPy5cv18MMP31WD/ixfvlwLFy5U5cqV5eXlpSJFiujRRx9V9uzZFRkZqYYNG1qpa4zRfffd5/K4QoUKLo8dDoe1Y5B05fj2/vvva+jQofLz89P48eP1/PPPu+WzwJOfQQkJCS7fL3x8fKyO6ZGapUuXOr9vJSUlKTo6Wtu2bXPZp1GjRtbbERYWpnnz5mnw4MEu6+fOnavSpUtbry955hh8tU6dOmn16tVasGCB/P399c0331z3s/F2++OPPzR//nzlypVLTz31lDJlck8syp49uz788EM988wz6tSpk+bNm6cDBw6oatWq2rp1q4oUKWK9DTly5NCsWbP0xBNPqEWLFho4cKC8vb1d9rE1/lSmTJn0xhtvqFGjRmrXrp3uu+8+HT9+XK1bt9bYsWOVPXt2K3WvlZCQoKNHj8rhcChHjhxu+f3flcHbGKNHHnnE+QM+f/68nnzySfn4+Ljst3HjRiv1H3roIe3evdv5uEaNGm4d2CVZjx499NxzzykgIEBFihRR7dq1JUmrV6+2euCrXbu2evfurY8//liBgYEu244fP66+ffs622LLjh07FBsbK+nK38OuXbtcBtuRZG1kVU///UkZ44vHq6++qhUrVui9995T69atNWnSJB0+fFhTpkzR8OHDrdVt27aty+Pnn3/eWq20VKlSRcOHD9f06dNTHOgTExP1zjvvqEqVKtbq79ix47r/xurUqaM33njDWv1kmTNnlpfXlTE+8+XLp5iYGJUqVUo5cuTQoUOHrNSsWbOmy/H3WtmyZdNDDz1kpbYkPfDAA5o/f74efPBBl/WlS5dWdHS06tSpY6321aZNm6aAgABJVwa6nDVrVorjcbdu3ay2IT4+Xvny5ZN0ZeDFY8eO6b777lNYWJjV45+nR63+9NNPNXDgQJ06dUqvvfaaXnrppRTHf5uSTzwkh+1z586pQoUKzn+LyWx96R40aJDLhYdhw4a59cLDtZ8BnTp1cnls+6RLskGDBqlJkybat2+fHn74YUlSdHS0PvnkE3322WfW60ueOQYn++mnnxQREaFMmTJpyZIlmjZtmqpXr6633npL3bt3t1pbkt5//3316tVLdevW1fbt25U3b17rNa91//33KywsTNHR0fL399fAgQPdErqT/fLLLxo0aJCKFy+u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9ZX2qx+768RHMnf2eoIrT81jn5GOwfHx8dq3b58kqVixYm4L3Nebzqpx48bWR1VPdurUKf3www9atWqVVq1ape3bt6tChQoun8u2GGO0adMmrVy5UitWrNCPP/6os2fPKiwszNoxMFnbtm0VHh7uMr2sO6U2l7rtY/BdGbyTHThwQLNmzdKHH36oQ4cOqU6dOnrhhRf09NNPu/Weo3379mnmzJmaPXu2jhw5onr16qlDhw7Wu9l8+eWXGjhwoPr06aOwsLAUcwbbOtv+4Ycf3tR+tqeTyp8/v0aMGKHWrVtbrXM9nrjinixv3rwaP368WrZs6bL+k08+UdeuXa13NT569KhatGihlStXOj/0Tp06pTp16mju3Lku9/zY4KluppK0evXqm9rP5r32M2bM0Ndff63g4GANGTJEwcHBzm3/93//p0cffVRPP/20tfqSVLBgQX3//fdu/dK3du1anThxQk888YRz3YcffqghQ4YoPj5ejRs31oQJE6zdY+/p+tKVcU5q1apl/R66G8mRI4c2b97sseCdK1cubdy4UaGhoSpWrJimTZumOnXqaN++fQoLC9P58+et1L329qq0uKP7oyd7Pd3t/vnnH3Xp0sWj89h74hh8tfbt22vcuHEpBnKLj49X165dNWPGDKv1PTWd1bVOnDihVatWacWKFVq5cqV27NihXLlyWf8e9uSTT+qnn37SmTNnVL58eeeUZg899JBb7vceNmyYRo8erUceeSTVK862brlMdqNjsZVjsLXx0v9jvvvuO9OqVSuTNWtWkzt3btO1a1e3tyEpKcl89tlnJnfu3G6ZSiK16VO8vLyc/7UlZ86caS65cuUyPj4+bnn/uXPnNr///rv1Oml5/fXXjZeXl6latap56qmnTOPGjV0W23LkyGH27NmTYv3u3btNjhw5rNdv1qyZqVy5stmxY4dz3fbt203lypVNixYtrNd/4oknzFNPPWWOHTtmAgICzI4dO8wPP/xgqlatalavXm219vWmMPLy8jJeXl5Wp/LIKN566y3Ttm1bc+nSJbfVrF+/vhk+fLjz8datW02mTJnMCy+8YEaPHm2Cg4PNkCFD7tj6xhgTGhpqcuXKZVq2bGnmzp1rTp8+bbVeWtq0aWPGjBnjkdrGGPPAAw+YL7/80hhjTMuWLU2DBg3Mjz/+aNq0aWN1Or+MYtCgQcbf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c+bMpmjRoqZo0aImc+bMpkKFCubQoUPW27FkyRLzxRdfGGOM2bt3rylRooRxOBwmMDDQREdHW6+/cuVKU61aNZM1a1bTv39/t95jlTVrVrN//37n46efftplXIvt27ebvHnzuq09Vzt9+rR59913TaVKlay8fufOnU316tXN6tWrTc+ePU2ePHlMQkKCc/tHH31kKleubKV2RqifHpcvXzZHjx51e90dO3aYXr16ub2uuzRr1sy8+OKLaW7v2LGjW8a56NKli8mePbspU6aM6dChg+nQoYMpW7asyZ49e4rPpNvt8uXLZtq0aaZly5bmkUceMXXq1HFZbJs6darx9vY2QUFBpnz58iY8PNy5VKhQwXp9Y4z54YcfTEBAgOncubPx8/Mz3bt3N48++qjx9/c3v/76q1vakBrbx+CrHTx40K3fv5Pt3r3b/Pzzzy7rvv/+e1O7dm1TpUoV89Zbb7mlHe+++64JDAw0w4YNM1myZHHe5z9z5kxTu3Zt6/WLFStmvv/+e2OMMQEBAc76O3fuNDlz5rRe/9qxjRo2bGiKFClicuTIYZ5++mnr9dPyyy+/mBIlSlh57bvyivePP/6oIUOG6Pnnn1eePHkkXbnHw1wzl6ktf/75p0v3otSmM5LsXHG++uyep870lStXTvv371fXrl3Vo0cPZc2aVfHx8Sn2c+dcip7g6SvunmL+//1UhQoV0saNG/X9999r165dkqRSpUqpbt26bmmHJ7uZPv744/r+++/Vvn17LViwwGVEcXfw8/PTP//843y8bt06jRw50mX7uXPn3NqmFStWaMaMGZo/f75y5MhhbUT1N998U02aNFGtWrUUEBCgDz74wGUWixkzZqhevXpWameE+pJUuHBhbdq0yfn5N3HiRLVp0ybFMdfb29v67ALJ4uPjNXfuXE2fPl3r1q1T6dKlNWrUKLfUdrf169dr9uzZaW5v3bq19Vk9JM/1epKudPGcNWuWGjZsqLJly7r9M2/YsGF666231LdvX7fWvdoDDzygzZs3a/jw4QoLC9OyZctUsWJFrV271i3z2F/LXcdgSTp+/Lji4+Ndbnncvn27Ro0a5ZzdoVWrVtbq9+3bV2FhYapataqkK71vnnzyST344IMqV66cIiMjlTVrVvXo0cNaGyRpwoQJev/999W4cWMNHz7cub5y5cpuud3k8OHDqfa2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s6vjP//845xa8eeff1b9+vW1aNEibd68WWXLlrVWFzcX/GyHj59++knTp0/XZ599pvvuu0/PP/+8Xn31VW3dutUtXSzhWREREdfd7unbcdzB399fW7Zs8ViXe08eg5966ikFBgbq/fff1/z58/Xcc88pNjbWObXeokWL1Lt3b2sXgA4ePKhHH31U+/btk7e3t8aPH6+XXnrJub1x48YKDQ3V2LFjrdRPdubMGeeglufPn9e5c+ec341+//13638bpUuX1o8//pjiFqeffvpJDRs2tHYB8tNPP1WzZs3S3H758mU1a9bM2gm4li1basOGDfrpp59SDCA6evRo9evXT7Nnz1aLFi1uf3Erd47/R3hyKg1jPD+dUbFixczkyZNTrH/vvffMvffea73+1Xbt2mUaN25svL29TZs2bZyDTeDOc+3ATnejqKioNJcePXqYLFmyWB1g8OqBDT0xpeC19uzZY/r3728KFChgsmfPblq2bOk8NsL9Dh06ZDp27OiWWmfPnjVTp0411atXNw6Hw9SuXdtMnTr1jh6Acc2aNebrr792WffBBx+YkJAQkzdvXtOxY0dz4cIFD7UO7lKnTh3z7bfferoZxhj3H4O3bNliAgMDjY+Pj/Hy8jIDBw502f7888+bTp06WatvjDGXLl0ymzdvNocPH06xbfPmzeb48eNW6xtjzAMPPJDqv/Vdu3aZggULWq8fERFhKlWqZM6cOeNct2rVKpM9e3YzZswYa3V9fX3NsmXLUt12+fJl06RJE6uDq126dMk0aNDAVKhQwZw+fdq5fsyYMSZTpkzm448/tlb7rr7ifW0Xh7Q4HA4tX77ccmuucNd0RtKVe9x79Oih9u3bq0aNGpKunOWaNWuWxo0bp06dOllvw5EjRzRkyBB98MEHql+/viIjI7nadYf74IMP1KJFC/n6+kpy73R6GdnJkyf15ptv6r333lO1atX0zjvvWOvmlSdPHmXLlk3t2rVT69atU3QxTmazq2NqkpKStGjRIk2fPl3ffvutEhIS3FofV2zZskUVK1a0eo9panbu3Klp06bpo48+0smTJ90ynY0nNGjQQHXq1HFOZfXbb7+pYsWKateunUqVKqWRI0eqU6dOev311z3b0Dvcn3/+qa+++irVzx9bAytt3brV+f/79u3TwIED1adPn1TvMy9XrpyVNlyPO4/Bx48f108//aTg4GBVq1bNZduiRYtUunTp694S4E7Zs2fX5s2bVbRo0dv6uo899pgcDoe++uor5/3tO3fu1MMPP6xmzZpp3Lhxt7XetZKSkvTss8/q5MmTWrp0qdasWaNGjRpp2LBh6t69u7W648aN08CBA/X999+7/O4TExPVrFkz/fjjj1q+fLnKlCljrQ3//POP6tatK29vby1btkyTJ09W7969NWvWLD3//PPW6t7VV7xhzPz5803NmjVN7ty5Te7cuU3NmjXNggULrNc9deqUefXVV02WLFlM9erVzerVq63XRMZyt06nd63z58+bYcOGmZw5c5ry5cu7ZYqdhIQEM3fuXFOvXj2TJUsW88wzz5jFixe7ZRqvm3W394rwpM2bN3v03+ClS5fu6B4PwcHB5pdffnE+HjBggKlZs6bz8aeffmpKlSrliaa51WeffWaaNm1qqlWrZipUqOCy2Pb999+brFmzmrJly5pMmTKZ8PBwkzNnTpMjRw5Tp04da3Wv/bxLradRRplSNSMdg8uWLWtiYmI8Vv/qqbZup/Pnz5saNWqYZs2amaSkJPPbb7+ZfPnyWetpm5qEhARTt25dU6NGDRMQEGAmTJjglrqDBw82uXPnNtu2bTPGXLnS/cwzz5i8efOa3377zS1tOHXqlClfvrwpXbq0yZQpk9Up7JLd1aOa382MMfr999913333aeXKlc4zbe4wYsQIvfPOOwoODtYnn3yip556ym21kXFkhOn0PCkxMVHvv/++hg4dKj8/P40fP17PP/+8W3q7+Pj4qHnz5mrevLliYmI0a9YsdenSRQkJCWrbtq2GDh3qlmNCu3btNGnSJOeANskOHjyo1q1b64cffrDeBnhWWtMppdUL407w999/KygoyPl41apVeuyxx5yPq1SpokOHDnmiaW4zfvx4vfbaa2rXrp0WLlyoiIgI7du3T7/88otefvll6/X79++v3r17a+jQocqWLZu++OIL5cuXT88995waNGhgrW5GHDBv7969WrFiRYp/gw6HQ4MGDfJgy/7n4MGDd2QPmCxZsmjRokWqXbu2mjVrptWrV6tNmzYaOXKktZpX97pI9vrrr6tly5Z6/vnn9dBDDzn3sdnrYujQoTp58qTq1aunFStWaODAgVq1apWio6Ot93z96quvnP//0ksvqXv37mrcuLFy5Mjhss1Kz0vr0R4Zzv79+03ZsmWdVxYLFy7scvbdNofDYbJmzWoaNWpknn766TQX3Nny5MljtmzZYowxJnv27GbXrl3GGGOio6NNeHi4J5tm3bx580zx4sVN3rx5TVRUlElISPB0k8z+/ftNnTp1jJeXlzlx4oRbaoaHh5uiRYuaNWvWONfNmjXLZM+e3TRu3NgtbUBK7rrivXbtWhMaGprqFcCMcMXPlsKFC5tVq1YZY65cbcqSJYv5/vvvndu3bt1qcuXK5anmuUWJEiXMnDlzjDGuVxMHDRpkXn75Zev1AwICzO+//26MMSZnzpzOq26bN282RYoUsV7fmCv30l66dCnF+kuXLjn/PmybOnWq8fb2NkFBQaZ8+fImPDzcubij58HNsnXF2RP1T58+nWLZtWuXKVSokHnppZdc1tuQWq+La3sduvMY/Nxzzxk/Pz8TGBjo/E5oW1o9TtzxGcQV77tQnz59dPnyZX300Ufy8/PTqFGj9OKLL2rjxo1uqd+mTZs7fp5m3FhiYqJz/tDAwEAdOXJEJUqUUJEiRbR7924Pt86uFi1aKEuWLGrZsqX++OMP9evXL9X9bN1nmCwhIUFffPGFZsyYobVr16phw4ZatGhRihFObVm/fr0GDBig2rVrq1evXvr999/17bffasyYMerYsaNb2nA3atKkyXW3255KM1nnzp1VuXJlLVq0KNXplO5Ujz/+uPr166d33nlHCxYsUNasWfXggw86t2/dulXFihXzYAvti4mJcY4tkyVLFufc5a1bt9b999+viRMnWq3v7+/vvK87f/782rdvn/N+0uPHj1utnaxOnTqpzvBx+vRp1alTxy1jLAwbNkxvvfWWc7wB2JczZ85Uj3XGGE2ePFlTpkyRMcbaXO4ZodfF1fN358qVS8YYhYeHa9asWS772foOdL35u20jeN+FfvzxR33++ed64IEHJEn333+/7rnnHsXHx6fo8mnDtf+wcHcqW7astmzZotDQUFWrVk0jRoyQj4+Ppk6detsHMMloHnrooRtOF2YzhKxfv14zZ87U3LlzFRISooiICH366aduC9zJMmfOrJEjRypr1qx68803lSlTJq1atUrVq1d3azvuNjcaNC9Hjhxq06aN9Xbs3btXn3/+ucemU/KUN998U02aNFGtWrUUEBCgDz74QD4+Ps7tM2bMUL169TzYQvuCg4N18uRJ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rnhLXEZGBq5fvw6FQoEWLVqgffv2YqdERERERESkVVh403sZGBggIyMDtra2YqdCREREpFXKyspQXl6u8pyBgYFI2RCRUNhcjd6L92aIiIiI1Ke4uBjffPMNTExMUK9ePRgbG6t8EJH2YeFNRERERKRBYWFhOHz4MKKioqCrq4uffvoJc+bMgYWFBTZu3Ch2ekQkAG41p/eqX78+MjMzudWciIiISA2aNWuGjRs3olevXjAwMMC5c+dgZ2eH+Ph4bNmyBcnJyWKnSERqxhVvIiIiIiINevTokXJBw8DAQDk+rEePHjh27JiYqRGRQFh403u9GjdGRERERP87W1tb5ObmAgBatWqFxMREAEBSUhKMjIxEzIyIhMLCm96LpxGIiIiI1CcwMBCZmZkAgGnTpmH16tWoU6cOJk2ahKlTp4qcHREJoZbYCdDH79dff0WTJk3EToOIiIjob62yshJLlizB3r17UV5ejnv37mHWrFnIzs5Geno67Ozs4OTkJHaaRCQANlejavLz8zFr1ixER0eLnQoRERGR1pg3bx5mz54NNzc31K1bF/v27cOXX37J91xEEsDCm6rJzMxEhw4dUFFRIXYqRERERFrD3t4eU6ZMwejRowEABw8ehIeHB0pLSyGX8wQokTbjVnMJ2rt37zuv5+TkaCgTIiIiIunIy8vDwIEDlY/d3Nwgk8lw7949WFpaipgZEQmNhbcEeXt7QyaTvbNpGjuZExEREanXy5cvUadOHZXnateujRcvXoiUERFpCgtvCTI3N8eaNWvg5eVV4/WMjAx07NhRw1kRERERaTeFQoGAgADo6uoqnysrK8OYMWNQr1495XM7d+4UIz0iEhALbwnq2LEj0tPT31p4v281nIiIiIj+upEjR1Z7zs/PT4RMiEjT2FxNgo4fP47i4mIMGDCgxuvFxcU4e/YsXF1dNZwZERERERGR9mHhLUE5OTmwsbHhOW4iIiIiIiIN4NwCCbK3t8eDBw+Uj4cNG4b79++LmBEREREREZH2YuEtQW9uckhOTkZxcbFI2RAREREREWk3Ft5EREREREREAmLhLUEymaza+W6e9yYiIiIiIhIGx4lJ0JszJGuaHwlwhiQREREREZE6sPCWoDdnSHJ+JBERERERkXA4ToyIiIiIiIhIQDzjTURERERERCQgFt5EREREREREAmLhTURERERERCQgFt5EREREREREAmLhTURERERERCQgFt5EREREREREAmLhTURERERERCQgFt5EREREREREAvp/8Jzv1+Nm2z0AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# MI between each feature and arousal\n",
    "mi_scores = mutual_info_regression(X_mi, y, random_state=42)\n",
    "mi_series = pd.Series(mi_scores, index=X.columns)\n",
    "mi_series.sort_values(ascending=False).plot(kind='bar', figsize=(12, 6), title='Mutual Information Scores')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "c2aec563",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "pVLF                 0.165426\n",
       "aVLF                 0.133885\n",
       "F1_CrossingPoints    0.133037\n",
       "NN50                 0.124604\n",
       "nLF                  0.041493\n",
       "nHF                  0.040712\n",
       "pLF                  0.037955\n",
       "aTotal               0.031338\n",
       "aHF                  0.030152\n",
       "pNN50                0.023663\n",
       "RMSSD                0.023284\n",
       "F3_MaxArea           0.017775\n",
       "SD1                  0.017523\n",
       "SD2                  0.015862\n",
       "LF/HF                0.014821\n",
       "F2_MinArea           0.014177\n",
       "aLF                  0.013822\n",
       "SDNN                 0.004924\n",
       "pHF                  0.004887\n",
       "Mean RR              0.000000\n",
       "dtype: float64"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mi_series.sort_values(ascending=False).head(20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "3a4bdfac",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>RMSSD</th>\n",
       "      <th>NN50</th>\n",
       "      <th>pNN50</th>\n",
       "      <th>aVLF</th>\n",
       "      <th>aHF</th>\n",
       "      <th>aTotal</th>\n",
       "      <th>pVLF</th>\n",
       "      <th>pLF</th>\n",
       "      <th>nLF</th>\n",
       "      <th>nHF</th>\n",
       "      <th>F1_CrossingPoints</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.352012</td>\n",
       "      <td>-0.471698</td>\n",
       "      <td>0.199388</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>1.194322</td>\n",
       "      <td>0.949087</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>-0.616404</td>\n",
       "      <td>-0.617551</td>\n",
       "      <td>0.122455</td>\n",
       "      <td>-0.538462</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.700875</td>\n",
       "      <td>-0.528302</td>\n",
       "      <td>0.278150</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>0.537748</td>\n",
       "      <td>0.463529</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>-0.237624</td>\n",
       "      <td>-0.239903</td>\n",
       "      <td>0.047571</td>\n",
       "      <td>-0.532967</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.587072</td>\n",
       "      <td>-0.811321</td>\n",
       "      <td>0.219158</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>2.454736</td>\n",
       "      <td>1.874433</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>0.198291</td>\n",
       "      <td>-0.802198</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.246371</td>\n",
       "      <td>-0.169811</td>\n",
       "      <td>0.162264</td>\n",
       "      <td>8.750069</td>\n",
       "      <td>-0.468002</td>\n",
       "      <td>-0.413262</td>\n",
       "      <td>15.617413</td>\n",
       "      <td>0.187468</td>\n",
       "      <td>0.245816</td>\n",
       "      <td>-0.048743</td>\n",
       "      <td>-0.049451</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.242915</td>\n",
       "      <td>-0.547170</td>\n",
       "      <td>-0.024673</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>0.637673</td>\n",
       "      <td>0.515692</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>-0.387740</td>\n",
       "      <td>-0.389570</td>\n",
       "      <td>0.077248</td>\n",
       "      <td>-0.560440</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      RMSSD      NN50     pNN50      aVLF       aHF    aTotal       pVLF  \\\n",
       "0  0.352012 -0.471698  0.199388 -1.000000  1.194322  0.949087  -1.000000   \n",
       "1  0.700875 -0.528302  0.278150 -1.000000  0.537748  0.463529  -1.000000   \n",
       "2  0.587072 -0.811321  0.219158 -1.000000  2.454736  1.874433  -1.000000   \n",
       "3  0.246371 -0.169811  0.162264  8.750069 -0.468002 -0.413262  15.617413   \n",
       "4  0.242915 -0.547170 -0.024673 -1.000000  0.637673  0.515692  -1.000000   \n",
       "\n",
       "        pLF       nLF       nHF  F1_CrossingPoints  \n",
       "0 -0.616404 -0.617551  0.122455          -0.538462  \n",
       "1 -0.237624 -0.239903  0.047571          -0.532967  \n",
       "2 -1.000000 -1.000000  0.198291          -0.802198  \n",
       "3  0.187468  0.245816 -0.048743          -0.049451  \n",
       "4 -0.387740 -0.389570  0.077248          -0.560440  "
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "selected_features = selected_features = mi_series[mi_series > 0.02].index.tolist()\n",
    "X = df[selected_features]\n",
    "X.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "54d1d24a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total raws after deleting the Nans: 2052\n"
     ]
    }
   ],
   "source": [
    "filtered_df = df.dropna(subset=selected_features + ['Arousal'])  # Keeping only valid raws\n",
    "print(f\"Total raws after deleting the Nans:\", len(filtered_df))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "c78bc1cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "X = filtered_df[selected_features]\n",
    "y = filtered_df['Arousal']\n",
    "groups = filtered_df['Participant']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "4c78c0b2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "LOPO without hyperparameter tuning with most significant features:\n",
      "RMSE: 0.169 ± 0.032\n",
      "MAE: 0.132 ± 0.028\n",
      "R² Score: 0.218 ± 0.207\n",
      "Correlation: 0.5145\n",
      "P-value: 4.7390e-139\n",
      "Concordance Correlation Coefficient (CCC): 0.4896\n"
     ]
    }
   ],
   "source": [
    "true_values = []\n",
    "predicted_values = []\n",
    "results = []\n",
    "\n",
    "for train_idx, test_idx in logo.split(X, y, groups):\n",
    "    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]\n",
    "    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]\n",
    "    test_participant = groups.iloc[test_idx].unique()[0]\n",
    "\n",
    "    model = XGBRegressor(n_estimators=100, random_state=42)\n",
    "    model.fit(X_train, y_train)\n",
    "    y_pred = model.predict(X_test)\n",
    "\n",
    "    true_values.extend(y_test)\n",
    "    predicted_values.extend(y_pred)\n",
    "\n",
    "    mse = mean_squared_error(y_test, y_pred)\n",
    "    rmse = np.sqrt(mse)\n",
    "    mae = mean_absolute_error(y_test, y_pred)\n",
    "    r2 = r2_score(y_test, y_pred)\n",
    "\n",
    "    results.append({\n",
    "        'Participant': test_participant,\n",
    "        'RMSE': rmse,\n",
    "        'MAE': mae,\n",
    "        'R2': r2\n",
    "    })\n",
    "\n",
    "\n",
    "results_df = pd.DataFrame(results)\n",
    "print(\"LOPO without hyperparameter tuning with most significant features:\")\n",
    "evaluate_regression(true_values, predicted_values, results_df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "2f558a30",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Nested LOPO with hyperparameter tuning:\n",
      "RMSE: 0.154 ± 0.034\n",
      "MAE: 0.128 ± 0.033\n",
      "R² Score: 0.350 ± 0.092\n",
      "Correlation: 0.5975\n",
      "P-value: 7.2221e-199\n",
      "Concordance Correlation Coefficient (CCC): 0.4851\n"
     ]
    }
   ],
   "source": [
    "true_values = []\n",
    "predicted_values = []\n",
    "results = [] \n",
    "param_grid = {\n",
    "    'n_estimators': [100, 200],\n",
    "    'max_depth': [3, 5],\n",
    "    'learning_rate': [0.01, 0.1],\n",
    "    'subsample': [0.8, 1.0]\n",
    "}\n",
    "\n",
    "for train_idx, test_idx in logo.split(X, y, groups):\n",
    "    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]\n",
    "    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]\n",
    "    test_participant = groups.iloc[test_idx].unique()[0]\n",
    "\n",
    "    inner_cv = KFold(n_splits=5, shuffle=True, random_state=42)\n",
    "    grid = GridSearchCV(XGBRegressor(random_state=42), param_grid,\n",
    "                        cv=inner_cv, scoring='neg_mean_squared_error', n_jobs=-1)\n",
    "    grid.fit(X_train, y_train)\n",
    "    best_model = grid.best_estimator_\n",
    "\n",
    "    y_pred = best_model.predict(X_test)\n",
    "\n",
    "    true_values.extend(y_test)\n",
    "    predicted_values.extend(y_pred)\n",
    "\n",
    "    mse = mean_squared_error(y_test, y_pred)\n",
    "    rmse = np.sqrt(mse)\n",
    "    mae = mean_absolute_error(y_test, y_pred)\n",
    "    r2 = r2_score(y_test, y_pred)\n",
    "\n",
    "\n",
    "    # Saving Parameters \n",
    "    results.append({\n",
    "        'Participant': test_participant,\n",
    "        'RMSE': rmse,\n",
    "        'MAE': mae,\n",
    "        'R2': r2,\n",
    "        **grid.best_params_\n",
    "    })\n",
    "\n",
    "results_df = pd.DataFrame(results)\n",
    "print(\"Nested LOPO with hyperparameter tuning:\")\n",
    "evaluate_regression(true_values, predicted_values, results_df)\n",
    "# For further analysis of the best params\n",
    "params_df = results_df.drop(columns=['Participant', 'RMSE'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "85122944",
   "metadata": {},
   "source": [
    "Best Parameters per Participant\n",
    "\n",
    "To understand whether certain model configurations generalize better, the best hyperparameters selected during each LOPO iteration were tracked.\n",
    "\n",
    "Below:\n",
    "- The most commonly selected configuration.\n",
    "- The configuration that resulted in the lowest average RMSE across participants.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "37d3ba86",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Most Common Configurations:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>MAE</th>\n",
       "      <th>R2</th>\n",
       "      <th>learning_rate</th>\n",
       "      <th>max_depth</th>\n",
       "      <th>n_estimators</th>\n",
       "      <th>subsample</th>\n",
       "      <th>Count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.064744</td>\n",
       "      <td>0.283422</td>\n",
       "      <td>0.01</td>\n",
       "      <td>3</td>\n",
       "      <td>200</td>\n",
       "      <td>0.8</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.071221</td>\n",
       "      <td>0.399630</td>\n",
       "      <td>0.01</td>\n",
       "      <td>3</td>\n",
       "      <td>200</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.072673</td>\n",
       "      <td>0.393529</td>\n",
       "      <td>0.01</td>\n",
       "      <td>3</td>\n",
       "      <td>200</td>\n",
       "      <td>0.8</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        MAE        R2  learning_rate  max_depth  n_estimators  subsample  \\\n",
       "0  0.064744  0.283422           0.01          3           200        0.8   \n",
       "1  0.071221  0.399630           0.01          3           200        1.0   \n",
       "2  0.072673  0.393529           0.01          3           200        0.8   \n",
       "\n",
       "   Count  \n",
       "0      1  \n",
       "1      1  \n",
       "2      1  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best Performing Configurations (Lowest Avg. RMSE):\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>n_estimators</th>\n",
       "      <th>max_depth</th>\n",
       "      <th>learning_rate</th>\n",
       "      <th>subsample</th>\n",
       "      <th>RMSE</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>200</td>\n",
       "      <td>3</td>\n",
       "      <td>0.01</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.149731</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>200</td>\n",
       "      <td>3</td>\n",
       "      <td>0.01</td>\n",
       "      <td>0.8</td>\n",
       "      <td>0.150436</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>200</td>\n",
       "      <td>5</td>\n",
       "      <td>0.01</td>\n",
       "      <td>0.8</td>\n",
       "      <td>0.153039</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   n_estimators  max_depth  learning_rate  subsample      RMSE\n",
       "1           200          3           0.01        1.0  0.149731\n",
       "0           200          3           0.01        0.8  0.150436\n",
       "2           200          5           0.01        0.8  0.153039"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# The most used configuration\n",
    "most_common_configs = (\n",
    "    params_df.value_counts()\n",
    "    .reset_index(name='Count')\n",
    "    .sort_values(by='Count', ascending=False)\n",
    "    .head(3)\n",
    ")\n",
    "print(\"Most Common Configurations:\")\n",
    "display(most_common_configs)\n",
    "\n",
    "# The best config for better results\n",
    "best_avg_configs = (\n",
    "    results_df\n",
    "    .groupby(['n_estimators', 'max_depth', 'learning_rate', 'subsample'])['RMSE']\n",
    "    .mean()\n",
    "    .reset_index()\n",
    "    .sort_values(by='RMSE')\n",
    "    .head(3)\n",
    ")\n",
    "print(\"Best Performing Configurations (Lowest Avg. RMSE):\")\n",
    "display(best_avg_configs)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "de03f252",
   "metadata": {},
   "source": [
    "**Random Forest Regressor**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "61676415",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RMSE: 0.156 ± 0.033\n",
      "MAE: 0.125 ± 0.033\n",
      "R² Score: 0.340 ± 0.115\n",
      "Correlation: 0.5839\n",
      "P-value: 7.5337e-188\n",
      "Concordance Correlation Coefficient (CCC): 0.5197\n"
     ]
    }
   ],
   "source": [
    "true_values = []\n",
    "predicted_values = []\n",
    "results_df = []\n",
    "\n",
    "for train_idx, test_idx in logo.split(X, y, groups):\n",
    "    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]\n",
    "    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]\n",
    "    test_participant = groups.iloc[test_idx].unique()[0]\n",
    "\n",
    "    model = RandomForestRegressor(n_estimators=100, random_state=42)\n",
    "    model.fit(X_train, y_train)\n",
    "    y_pred = model.predict(X_test)\n",
    "\n",
    "    true_values.extend(y_test)\n",
    "    predicted_values.extend(y_pred)\n",
    "\n",
    "    mse = mean_squared_error(y_test, y_pred)\n",
    "    rmse = np.sqrt(mse)\n",
    "    mae = mean_absolute_error(y_test, y_pred)\n",
    "    r2 = r2_score(y_test, y_pred)\n",
    "\n",
    "    results.append({\n",
    "        'Participant': test_participant,\n",
    "        'RMSE': rmse,\n",
    "        'MAE': mae,\n",
    "        'R2': r2\n",
    "    })\n",
    "\n",
    "\n",
    "results_df = pd.DataFrame(results)\n",
    "evaluate_regression(true_values, predicted_values, results_df)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "80e39f93",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RMSE: 0.154 ± 0.032\n",
      "MAE: 0.122 ± 0.033\n",
      "R² Score: 0.357 ± 0.125\n",
      "Correlation: 0.5975\n",
      "P-value: 7.9171e-199\n",
      "Concordance Correlation Coefficient (CCC): 0.5334\n"
     ]
    }
   ],
   "source": [
    "true_values = []\n",
    "predicted_values = []\n",
    "best_params_list = []\n",
    "results = []\n",
    "\n",
    "# Hyperparameters tunning\n",
    "param_grid = {\n",
    "    'n_estimators': [100, 200],\n",
    "    'max_depth': [None, 10, 20],\n",
    "    'min_samples_split': [2, 5],\n",
    "    'min_samples_leaf': [1, 2]\n",
    "}\n",
    "\n",
    "for train_idx, test_idx in logo.split(X, y, groups):\n",
    "    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]\n",
    "    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]\n",
    "    test_participant = groups.iloc[test_idx].unique()[0]\n",
    "\n",
    "    inner_cv = KFold(n_splits=5, shuffle=True, random_state=42)\n",
    "\n",
    "    grid = GridSearchCV(\n",
    "        estimator=RandomForestRegressor(random_state=42),\n",
    "        param_grid=param_grid,\n",
    "        cv=inner_cv,\n",
    "        scoring='neg_mean_squared_error',\n",
    "        n_jobs=-1\n",
    "    )\n",
    "\n",
    "    grid.fit(X_train, y_train)\n",
    "    best_model = grid.best_estimator_\n",
    "    y_pred = best_model.predict(X_test)\n",
    "\n",
    "    true_values.extend(y_test)\n",
    "    predicted_values.extend(y_pred)\n",
    "    best_params_list.append(grid.best_params_)\n",
    "\n",
    "    \n",
    "    mse = mean_squared_error(y_test, y_pred)\n",
    "    rmse = np.sqrt(mse)\n",
    "    mae = mean_absolute_error(y_test, y_pred)\n",
    "    r2 = r2_score(y_test, y_pred)\n",
    "\n",
    "    results.append({\n",
    "        'Participant': test_participant,\n",
    "        'RMSE': rmse,\n",
    "        'MAE': mae,\n",
    "        'R2': r2,\n",
    "        **grid.best_params_\n",
    "    })\n",
    "\n",
    "\n",
    "results_df = pd.DataFrame(results)\n",
    "evaluate_regression(true_values, predicted_values, results_df)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "7436f4f8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Best hyperparameters per participant:\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "max_depth  min_samples_leaf  min_samples_split  n_estimators\n",
       "10         2                 2                  200             22\n",
       "                             5                  200             21\n",
       "                             2                  100              7\n",
       "           1                 2                  200              3\n",
       "           2                 5                  100              1\n",
       "Name: count, dtype: int64"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "best_params_df = pd.DataFrame(best_params_list)\n",
    "print(\"\\nBest hyperparameters per participant:\")\n",
    "display(best_params_df.value_counts().head())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "178597c7",
   "metadata": {},
   "source": [
    "Support Vector Regressor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "33b5bcac",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SVR (rbf) with LOPO Results:\n",
      "RMSE: 0.170 ± 0.039\n",
      "MAE: 0.139 ± 0.037\n",
      "R² Score: 0.207 ± 0.162\n",
      "Correlation: 0.4602\n",
      "P-value: 4.5220e-108\n",
      "Concordance Correlation Coefficient (CCC): 0.3808\n"
     ]
    }
   ],
   "source": [
    "true_values = []\n",
    "predicted_values = []\n",
    "results = []\n",
    "\n",
    "for train_idx, test_idx in logo.split(X, y, groups):\n",
    "    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]\n",
    "    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]\n",
    "    test_participant = groups.iloc[test_idx].unique()[0]\n",
    "\n",
    "    model = make_pipeline(\n",
    "        StandardScaler(),\n",
    "        SVR(kernel='rbf', C=1.0, gamma='scale')\n",
    "    )\n",
    "\n",
    "    model.fit(X_train, y_train)\n",
    "    y_pred = model.predict(X_test)\n",
    "\n",
    "    true_values.extend(y_test)\n",
    "    predicted_values.extend(y_pred)\n",
    "\n",
    "    mse = mean_squared_error(y_test, y_pred)\n",
    "    rmse = np.sqrt(mse)\n",
    "    mae = mean_absolute_error(y_test, y_pred)\n",
    "    r2 = r2_score(y_test, y_pred)\n",
    "\n",
    "    results.append({\n",
    "        'Participant': test_participant,\n",
    "        'RMSE': rmse,\n",
    "        'MAE': mae,\n",
    "        'R2': r2\n",
    "    })\n",
    "\n",
    "results_df = pd.DataFrame(results)\n",
    "print(\"SVR (rbf) with LOPO Results:\")\n",
    "evaluate_regression(true_values, predicted_values, results_df)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "9ace5d0b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SVR (rbf) + Hyperparameter Tuning (LOPO):\n",
      "RMSE: 0.170 ± 0.038\n",
      "MAE: 0.139 ± 0.036\n",
      "R² Score: 0.209 ± 0.155\n",
      "Correlation: 0.4619\n",
      "P-value: 5.4016e-109\n",
      "Concordance Correlation Coefficient (CCC): 0.3814\n"
     ]
    }
   ],
   "source": [
    "true_values = []\n",
    "predicted_values = []\n",
    "results = []\n",
    "\n",
    "param_grid = {\n",
    "    'svr__C': [0.1, 1, 10],\n",
    "    'svr__gamma': ['scale', 0.01, 0.001],\n",
    "    'svr__kernel': ['rbf']\n",
    "}\n",
    "\n",
    "for train_idx, test_idx in logo.split(X, y, groups):\n",
    "    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]\n",
    "    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]\n",
    "    test_participant = groups.iloc[test_idx].unique()[0]\n",
    "\n",
    "    pipeline = make_pipeline(StandardScaler(), SVR())\n",
    "\n",
    "    \n",
    "    inner_cv = KFold(n_splits=5, shuffle=True, random_state=42)\n",
    "\n",
    "    # GridSearchCV \n",
    "    grid = GridSearchCV(\n",
    "        estimator=pipeline,\n",
    "        param_grid=param_grid,\n",
    "        cv=inner_cv,\n",
    "        scoring='neg_mean_squared_error',\n",
    "        n_jobs=-1\n",
    "    )\n",
    "\n",
    "    grid.fit(X_train, y_train)\n",
    "    best_model = grid.best_estimator_\n",
    "\n",
    "    y_pred = best_model.predict(X_test)\n",
    "\n",
    "    true_values.extend(y_test)\n",
    "    predicted_values.extend(y_pred)\n",
    "\n",
    "    mse = mean_squared_error(y_test, y_pred)\n",
    "    rmse = np.sqrt(mse)\n",
    "    mae = mean_absolute_error(y_test, y_pred)\n",
    "    r2 = r2_score(y_test, y_pred)\n",
    "\n",
    "    results.append({\n",
    "        'Participant': test_participant,\n",
    "        'RMSE': rmse,\n",
    "        'MAE': mae,\n",
    "        'R2': r2,\n",
    "        **grid.best_params_\n",
    "        \n",
    "    })\n",
    "\n",
    "results_df = pd.DataFrame(results)\n",
    "print(\"SVR (rbf) + Hyperparameter Tuning (LOPO):\")\n",
    "evaluate_regression(true_values, predicted_values, results_df)\n",
    "\n",
    "results_df = pd.DataFrame(results)\n",
    "params_df = results_df.drop(columns=['Participant', 'RMSE'])\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
